﻿//------------------------------------------------------------------------------
// <copyright file="ProgramReporisoty.cs" company="David Martos">
//     Copyright (c) David Martos.  All rights reserved.
// </copyright>
// <summary>Repository class for Program entity</summary>
//  ----------------------------------------------------------------------------
namespace Dissemination.MVC.Repositories
{

    #region using statements

    using System.Linq;
    using System.Collections.Generic;
    using Dissemination.MVC.Models;
    using Dissemination.MVC.ViewModels;
    using System.Data.Objects;

    #endregion

    /// <summary>
    /// Repository class for Program entity
    /// </summary>
    public class ProgramRepository : BaseRepository<Program>
    {

        #region Constructor

        /// <summary>
        /// Constructor method. Entity name initialization
        /// </summary>
        public ProgramRepository()
        {
            EntityName = "Programs";
        }

        #endregion

        #region Generic methods

        /// <summary>
        /// Gets the list of programs in the database
        /// </summary>
        /// <returns>List of programs</returns>
        public override List<Program> List()
        {
            if (log.IsDebugEnabled) log.Debug("Retrieving programs from database...");

            var result = from program in dataContext.Programs
                         select program;

            if (log.IsDebugEnabled) log.Debug("Programs retrieved from database.");

            // string sql = ((ObjectQuery<Program>)result).ToTraceString();

            return result.ToList();
        }

        /// <summary>
        /// Gets a single program with the given id
        /// </summary>
        /// <param name="id">Id</param>
        /// <returns>Program</returns>
        public override Program Get(int id)
        {
            if (log.IsDebugEnabled) log.Debug("Retrieving programs from database...");

            var result = dataContext.Programs.Include("TargetAreas.Country").Include("Surveys").FirstOrDefault(p => p.ProgramID == id);

            if (log.IsDebugEnabled) log.Debug("Retrieving programs from database...");

            return result;
        }

        #endregion

        /// <summary>
        /// Gets the list of target areas, sorted by code, of a given program
        /// </summary>
        /// <param name="programID">Program ID</param>
        /// <returns>List of target areas</returns>
        public List<TargetArea> GetTargetAreasByProgramID(int programID)
        {
            if (log.IsDebugEnabled) log.DebugFormat("Retrieving target areas from database, for program {0}...", programID);

            var result = dataContext.TargetAreas.Include("Country").Where(ta => ta.Program.ProgramID == programID).OrderBy(ta => ta.Country.CountryCode).ThenBy(ta => ta.TargetAreaOrdinal);

            if (log.IsDebugEnabled) log.DebugFormat("Retrieved target areas from database, for program {0}.", programID);

            // string sql = ((ObjectQuery<TargetArea>)result).ToTraceString();

            return result.ToList();
        }

        /// <summary>
        /// Gets the list of seminars included in a target area
        /// </summary>
        /// <param name="targetAreaID">The target area id</param>
        /// <returns>List of target areas</returns>
        public List<Seminar> GetSeminarsByTargetAreaID(int targetAreaID)
        {
            if (log.IsDebugEnabled) log.DebugFormat("Retrieving seminars from database, for target area {0}...", targetAreaID);

            var result = dataContext.Seminars.Include("Assessments").Include("FollowUps.Speciality").Include("FollowUps.Gender").Include("FollowUps.ProfessionalBackground").Include("TestResults").Where(s => s.TargetArea.TargetAreaID == targetAreaID);

            if (log.IsDebugEnabled) log.DebugFormat("Retrieving seminars from database, for target area {0}...", targetAreaID);

            return result.ToList();
        }

        public List<Seminar> GetSeminarsByProgramID(int programID)
        {
            if (log.IsDebugEnabled) log.DebugFormat("Retrieving seminars from database, for target area {0}...", programID);

            var result = dataContext.Seminars.Include("Participants.Gender").Include("TargetArea.Country").Where(s => s.TargetArea.Program.ProgramID == programID).OrderBy(s => s.TargetArea.Country.CountryCode).ThenBy(s => s.SeminarOrdinal);

            if (log.IsDebugEnabled) log.DebugFormat("Retrieving seminars from database, for target area {0}...", programID);

            return result.ToList();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public List<Reporter> GetReportersByTargetAreaID(int id)
        {
            return dataContext.Reporters.Include("Gender").Where(r => r.TargetArea.TargetAreaID == id).OrderBy(r => r.TargetArea.TargetAreaVisualCode).ThenBy(r => r.ReporterName).ThenBy(r => r.ReporterSurname).ToList();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public List<SurveyResult> GetSurveyResultsByTargetAreaID(int id)
        {
            return dataContext.SurveyResults.Include("Survey").Where(sr => sr.TargetArea.TargetAreaID == id).ToList();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Program GetDefaultProgram()
        {
            return dataContext.Programs.FirstOrDefault(p => p.ProgramIsDefault);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="programID"></param>
        /// <returns></returns>
        public SurveyResultsReportViewModel GetSurveyActivityReport(int programID)
        {
            var programViewModel = new ProgramViewModel
            { 
                Program = Get(programID),
                SortedTargetAreas = dataContext.TargetAreas.Include("Country").Include("SurveyResults").Where(ta => ta.Program.ProgramID == programID).OrderBy(ta => ta.Country.CountryID).ThenBy(ta => ta.TargetAreaOrdinal).ToList()
            };

            SurveyResultsReportViewModel viewModel = new SurveyResultsReportViewModel();
            viewModel.Program = programViewModel.Program;

            viewModel.Rows = new List<SurveyResultsReportRowViewModel>();
            foreach (var targetArea in programViewModel.SortedTargetAreas)
            {
                SurveyResultsReportRowViewModel row = new SurveyResultsReportRowViewModel();
                row.TargetArea = targetArea;
                row.SurveyResults = new List<bool>();
                foreach (var survey in programViewModel.Program.Surveys)
                {
                    SurveyResult result = targetArea.SurveyResults.FirstOrDefault(sr => sr.Survey.SurveyID == survey.SurveyID);
                    if (result != null)
                    {
                        row.SurveyResults.Add(result.SurveyResultsFilled);
                    }
                }
                
                viewModel.Rows.Add(row);
            }
            return viewModel;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="programID"></param>
        /// <returns></returns>
        public EODResultsReportViewModel GetEODActivityReport(int programID)
        {
            //TODO: este listado se puede mejorar
            var programViewModel = new ProgramViewModel
            {
                Program = Get(programID),
                SortedTargetAreas = dataContext.TargetAreas.Include("Country").Include("Seminars.Assessments").Include("Seminars.FollowUps").Include("Seminars.TestResults").Where(ta => ta.Program.ProgramID == programID).OrderBy(ta => ta.Country.CountryCode).ThenBy(ta => ta.TargetAreaOrdinal).ToList()
            };

            EODResultsReportViewModel viewModel = new EODResultsReportViewModel();
            viewModel.Program = programViewModel.Program;

            viewModel.Rows = new List<EODResultsReportRowViewModel>();

            int numberOfSeminars = dataContext.Seminars.Count(s => s.TargetArea.Program.ProgramID == programID);

            if (numberOfSeminars > 0)
            {
                int maxOrdinal = dataContext.Seminars.Where(s => s.TargetArea.Program.ProgramID == programID).Max(s => s.SeminarOrdinal);
                viewModel.MaxSeminars = maxOrdinal;
                foreach (var targetArea in programViewModel.SortedTargetAreas)
                {
                    int currentOrdinal = dataContext.TargetAreas.FirstOrDefault(ta => ta.TargetAreaID == targetArea.TargetAreaID).Seminars.Count;

                    EODResultsReportRowViewModel row = new EODResultsReportRowViewModel();
                    row.TargetArea = targetArea;
                    row.SeminarResults = new List<EODResultsReportCellViewModel>();
                    for (int i = 1; i <= currentOrdinal; i++)
                    {
                        EODResultsReportCellViewModel cell = new EODResultsReportCellViewModel();
                        bool test = dataContext.TestResults.Where(tr => tr.Seminar.TargetArea.TargetAreaID == targetArea.TargetAreaID && tr.Seminar.SeminarOrdinal == i).Any();
                        bool assessment = dataContext.Assessments.Where(tr => tr.Seminar.TargetArea.TargetAreaID == targetArea.TargetAreaID && tr.Seminar.SeminarOrdinal == i).Any();
                        bool followup = dataContext.FollowUps.Where(tr => tr.Seminar.TargetArea.TargetAreaID == targetArea.TargetAreaID && tr.Seminar.SeminarOrdinal == i).Any();
                        cell.Test = test;
                        cell.Assessment = assessment;
                        cell.FollowUp = followup;
                        row.SeminarResults.Add(cell);
                    }

                    viewModel.Rows.Add(row);
                }
            }
            return viewModel;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        public void ClearDefaultProgram(int id)
        {
            foreach (var program in dataContext.Programs)
            {
                if (program.ProgramID != id)
                {
                    program.ProgramIsDefault = false;
                }
            }
        }


        public void FixSurveyResults()
        {
            foreach (var ta in dataContext.TargetAreas.Include("Program.Surveys"))
            {
                foreach (var s in ta.Program.Surveys)
                {
                    if (dataContext.SurveyResults.Include("TargetArea").Include("Survey").FirstOrDefault(sr => sr.TargetArea.TargetAreaID == ta.TargetAreaID && sr.Survey.SurveyID == s.SurveyID) == null)
                    {
                        AddEmptySurveyResult(s, ta);
                    }
                }
            }

            dataContext.SaveChanges();
        }
    }
}
